/*
 * 文件名：SingUtils.java
 * 版权：Copyright by www.suyinchina.com
 * 描述：
 * 修改人：XLY
 * 修改时间：2015-1-16
 * 跟踪单号：
 * 修改单号：
 * 修改内容：
 */

package com.caiyouxi.pay.payment.weixin.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微信支付签名算法,obj是待签名对象，是一个model类,或map,注意不要带sign
 * 
 * @author Administrator
 * @version 2015-1-16
 * @see SignUtils
 * @since
 */
public class SignUtils
{
    public static String genereateSign(Object obj,String apiKey){
        StringBuffer sbf = new StringBuffer();
        
        if(obj instanceof Map){
            //传过来的是一个map
            Map map = (Map)obj;
            Object[] keyNames = map.keySet().toArray();
            Arrays.sort(keyNames);
            for(Object keyName:keyNames){
                Object val = map.get(keyName);
                if(val!=null&&!"".equals(val)){
                    sbf.append("&"+keyName+"="+val);
                }
            }
        }else{
            Class clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            String[] fieldNames = new String[fields.length];
            for(int i=0;i<fields.length;i++){
                fieldNames[i] = fields[i].getName();
            }
            Arrays.sort(fieldNames);
            for(String fieldName:fieldNames){
                try 
                {   
                    Field f = clazz.getDeclaredField(fieldName); 
                    f.setAccessible(true);
                    Object val = f.get(obj);
                    if(val!=null&&!"".equals(val)){
                        sbf.append("&"+fieldName+"="+val);
                    }
                }
                catch (IllegalArgumentException e)
                {
                    e.printStackTrace();
                }
                catch (SecurityException e)
                {
                    e.printStackTrace();
                }
                catch (IllegalAccessException e)
                {
                    e.printStackTrace();
                }
                catch (NoSuchFieldException e)
                {
                    e.printStackTrace();
                }
               
            }
        }
        String stringA = sbf.toString().substring(1);
        System.out.println("stringA:"+stringA);
        String stringSignTemp = stringA + "&key="+apiKey;
        System.out.println("stringSignTemp:"+stringSignTemp);
        String signValue = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
        System.out.println("签名是:"+signValue);
        return signValue;
    }
    
    
    /**
     * str,暂时不开放该方法 
     * Description: <br>
     * 
     * @param str示例  appId=wx66705c6709085479&nonceStr=nonceStr&package=prepay_id=prepay_id&signType=MD5&timeStamp=timeStamp
     * @param apiKey
     * @return 
     * @see
     */
    @Deprecated
    private static String genereateSign(String str,String apiKey){
        String stringSignTemp = str + "&key="+apiKey;
        System.out.println("stringSignTemp:"+stringSignTemp);
        String signValue = DigestUtils.md5Hex(stringSignTemp).toUpperCase();
        System.out.println("签名是:"+signValue);
        return signValue;
    }
    
    
    /**
     * 校验xml的签名是否正确，注意：请在result_code和return_code都为SUCCESS的情况下调用
     * Description: <br>
     * 
     * @param xml
     * @return 
     * @throws DocumentException 
     * @see
     */
    public static boolean checkSign(String xml,String apiKey) throws DocumentException{
        HashMap<String, String> xmlMap = new HashMap<String, String>();
        Document doc = DocumentHelper.parseText(xml);
        Element rootElement = doc.getRootElement();
        List<Element> elements =  rootElement.elements();
        String xmlSign = null;
        for(Element e:elements){
            if("sign".equals(e.getName())){
                xmlSign = e.getText();
                continue;
            }
            xmlMap.put(e.getName(), e.getText());
        }
        String gSign = genereateSign(xmlMap, apiKey);
        return gSign.equals(xmlSign)?true:false;
    }
    
}
